var normalProj = G_NORMAL_MAP.getProjection();

var PIXEL_DISTANCE_TH = 15;

var ACTIVE_TRACK_COLOR  = "#0000ff"; 
var PASSIVE_TRACK_COLOR = "#aa00bb";

// var POLYLINE_STATUS_UNDEFINED      = 0;
var POLYLINE_STATUS_INVISIBLE      = 1;
var POLYLINE_STATUS_VISIBLE        = 2;
var POLYLINE_STATUS_VISIBLE_ACTIVE = 3;


Section = function( sectionGData, status )
{
    this.m_polyline = new GPolyline.fromEncoded({
                color      : PASSIVE_TRACK_COLOR,
                opacity    : 1,
                weight     : 2,
                levels     : sectionGData.levels,
                points     : sectionGData.points,
                zoomFactor : sectionGData.zoom_factor,
                numLevels  : sectionGData.num_levels}, 
                //GPolylineOptions - undocumented feature of fromEncoded()!
                {clickable : false} );
                
    this.m_polyline.hide();

    this.m_zooms = {};
    // this.id_track = id_track;
    this.m_status = POLYLINE_STATUS_INVISIBLE;
    this.changeStatus( status );
    
    this.getPixelCoordinates = function(zoom)
    {
        //lazy calculation
        if ( this.m_zooms[zoom] ) return this.m_zooms[zoom];
        
        //calculate pixel coordinates for corresponding zoom
        var nVertex = this.m_polyline.getVertexCount();
        
        this.m_zooms[zoom] = new Array(nVertex);
        
        for (var curVertex = 0; curVertex < nVertex; curVertex++)
            this.m_zooms[zoom][curVertex] = normalProj.fromLatLngToPixel(this.m_polyline.getVertex(curVertex), zoom);
    
        return this.m_zooms[zoom];
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    this.Distance2Segment = function (point, s1, s2)
    {
        if (s2.x != s1.x) {
            var a = (s2.y - s1.y) / (s2.x - s1.x);
            var b = s2.y - a * s2.x;
            var dist = Math.abs(a*point.x + b - point.y) / Math.sqrt(a*a+1);

        }
        else {
            var dist = Math.abs(point.x - s2.x)
        };

        // length^2 of line segment 
        var rl2 = Math.pow(s2.y - s1.y,2) + Math.pow(s2.x - s1.x,2);
        
        // distance^2 of pt to end line segment
        var ln2 = Math.pow(s2.y - point.y,2) + Math.pow(s2.x - point.x,2);

        // distance^2 of pt to begin line segment
        var lnm12 = Math.pow(s1.y - point.y,2) + Math.pow(s1.x - point.x,2);

        // minimum distance^2 of pt to infinite line
        var dist2 = Math.pow(dist,2);

        // calculated length^2 of line segment
        var calcrl2 = ln2 - dist2 + lnm12 - dist2;

        // redefine minimum distance to line segment (not infinite line) if necessary
        if (calcrl2 > rl2) {
            dist = Math.sqrt( Math.min(ln2,lnm12) ); 
        };  
        
        return dist;
    }
}

Section.prototype.isNearClick = function( latlng, curZoom )
{
    var pixelCoords = this.getPixelCoordinates(curZoom);
        
    for (var c = 1; c < pixelCoords.length; c++)
        if (this.Distance2Segment(normalProj.fromLatLngToPixel(latlng, curZoom), pixelCoords[c-1], pixelCoords[c]) < PIXEL_DISTANCE_TH)
            return true;
            
    return false;
}

Section.prototype.changeStatus = function( newStatus )
{
    if ( this.m_status == newStatus ) return;
        
    switch ( newStatus )
    {
        case POLYLINE_STATUS_INVISIBLE:
            this.m_polyline.hide();
            break;
        case POLYLINE_STATUS_VISIBLE:
            this.m_polyline.setStrokeStyle( {color : PASSIVE_TRACK_COLOR} );
            if ( this.m_status == POLYLINE_STATUS_INVISIBLE )
                this.m_polyline.show();
            break;
        case POLYLINE_STATUS_VISIBLE_ACTIVE:
            this.m_polyline.setStrokeStyle( {color : ACTIVE_TRACK_COLOR} );
            if ( this.m_status == POLYLINE_STATUS_INVISIBLE )
                this.m_polyline.show();
            break;
        default: assert(true, "Unknown section status!");
    }
    
    this.m_status = newStatus;
}

Section.prototype.getPolyline = function()
{
    return this.m_polyline;
}

//bounds of type GLatLngBounds
Section.prototype.isVisibleInBounds = function( bounds )
{
    var nVertex = this.m_polyline.getVertexCount();
        
    for (var curVertex = 0; curVertex < nVertex; curVertex++)
        if ( bounds.containsLatLng( this.m_polyline.getVertex(curVertex) ) )
            return true;
            
    return false;
}